home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 19 / Amiga Plus Leser CD 19.iso / Tools / Freeware / Swf_Player / Lib / graphic32.cc < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-17  |  15.8 KB  |  658 lines

  1. ////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998 Olivier Debon
  4. // 
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. // 
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. // 
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. // 
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //  
  22.  
  23. #include "swf.h"
  24.  
  25. #include "graphic32.h"
  26.  
  27. extern unsigned char SQRT[];
  28.  
  29. #define FULL_AA
  30.  
  31. #define PRINT 0
  32.  
  33. typedef unsigned long TYPE;
  34.  
  35. GraphicDevice32::GraphicDevice32(FlashDisplay *fd) : GraphicDevice(fd)
  36. {
  37. }
  38.  
  39. long
  40. GraphicDevice32::allocColor(Color color)
  41. {
  42.     return (color.red)<<16 | (color.green)<<8 | (color.blue);
  43. }
  44.  
  45. void
  46. GraphicDevice32::clearCanvas()
  47. {
  48.     TYPE  pixel;
  49.     TYPE *point,*p;
  50.     long                 h, w,n;
  51.  
  52.     if (!bgInitialized) return;
  53.  
  54.     pixel = allocColor(backgroundColor);
  55.  
  56.     point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin;
  57.     w = clip_rect.xmax - clip_rect.xmin;
  58.     h = clip_rect.ymax - clip_rect.ymin;
  59.  
  60.     while (h--) {
  61.         p = point;
  62.         n = w;
  63.         while (n--) {
  64.             *p++ = pixel;
  65.         }
  66.  
  67.         point = (TYPE *)((char *)point + bpl);
  68.     }
  69.  
  70.     flashDisplay->flash_refresh = 1;
  71.     flashDisplay->clip_x = clip_rect.xmin;
  72.     flashDisplay->clip_y = clip_rect.ymin;
  73.     flashDisplay->clip_width  = clip_rect.xmax-clip_rect.xmin;
  74.     flashDisplay->clip_height = clip_rect.ymax-clip_rect.ymin;
  75. }
  76.  
  77. #define RED_MASK   0xFF0000
  78. #define GREEN_MASK 0x00FF00
  79. #define BLUE_MASK  0x0000FF
  80.  
  81. /* alpha = 0 : select c1, alpha = 255 select c2 */
  82. static inline unsigned long
  83. mix_alpha(unsigned long c1, unsigned long c2, int alpha)
  84. {
  85.     long r1,r2,r;
  86.     long g1,g2,g;
  87.     long b1,b2,b;
  88.  
  89.     r1 = c1 & RED_MASK;
  90.     r2 = c2 & RED_MASK;
  91.     r = (((r2-r1)*alpha + r1 * 256) >> 8) & RED_MASK;
  92.  
  93.     g1 = c1 & GREEN_MASK;
  94.     g2 = c2 & GREEN_MASK;
  95.     g = (((g2-g1)*alpha + g1 * 256) >> 8) & GREEN_MASK;
  96.  
  97.     b1 = c1 & BLUE_MASK;
  98.     b2 = c2 & BLUE_MASK;
  99.     b = (((b2-b1)*alpha + b1 * 256) >> 8) & BLUE_MASK;
  100.  
  101.     return (r|g|b);
  102. }
  103.  
  104. void
  105. GraphicDevice32::fillLineAA(FillStyleDef *f, long y, long start, long end)
  106. {
  107.     register long   n;
  108.     TYPE *line;
  109.     TYPE *point,pixel;
  110.     unsigned int alpha, start_alpha,end_alpha;
  111.     
  112.     if (clip(y,start,end)) return;
  113.     
  114.     line = (TYPE *)(canvasBuffer + bpl*y);
  115.     
  116.     alpha = f->color.alpha;
  117.     pixel = f->color.pixel;
  118.     
  119.     if (alpha == ALPHA_OPAQUE) {
  120.  
  121.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  122.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  123.         
  124.         start >>= FRAC_BITS;
  125.         end >>= FRAC_BITS;
  126.         
  127.         point = &line[start];
  128.  
  129.         if (start == end) {
  130.             *point = mix_alpha(*point, pixel, start_alpha + end_alpha - 255);
  131.         } else {
  132.             n = end-start;
  133.             if (start_alpha < 255) {
  134.                 *point = mix_alpha(*point, pixel, start_alpha);
  135.                 point++;
  136.                 n--;
  137.             }
  138.             while (n > 0) {
  139.                 *point = pixel;
  140.                 point++;
  141.                 n--;
  142.             }
  143.             if (end_alpha > 0) {
  144.                 *point = mix_alpha(*point, pixel, end_alpha);
  145.             }
  146.         }
  147.     } else {
  148.  
  149.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  150.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  151.  
  152.         start >>= FRAC_BITS;
  153.         end >>= FRAC_BITS;
  154.         
  155.         point = &line[start];
  156.         
  157.         if (start == end) {
  158.             *point = mix_alpha(*point, pixel, 
  159.                                ((start_alpha + end_alpha - 255) * alpha) >> 8);
  160.         } else {
  161.             n = end-start;
  162.             if (start_alpha < 255) {
  163.                 *point = mix_alpha(*point, pixel, (start_alpha * alpha) >> 8);
  164.                 point++;
  165.                 n--;
  166.             }
  167.             while (n > 0) {
  168.                 *point = mix_alpha(*point, pixel, alpha);
  169.                 point++;
  170.                 n--;
  171.             }
  172.             if (end_alpha > 0) {
  173.                 *point = mix_alpha(*point, pixel, (end_alpha * alpha) >> 8);
  174.             }
  175.         }
  176.     }
  177. }
  178.  
  179. void
  180. GraphicDevice32::fillLine(FillStyleDef *f, long y, long start, long end)
  181. {
  182.     register long   n;
  183.         TYPE *line,*point;
  184.         TYPE pixel;
  185.         unsigned int alpha;
  186.  
  187.     if (clip(y,start,end)) return;
  188.  
  189.         start >>= FRAC_BITS;
  190.         end >>= FRAC_BITS;
  191.  
  192.     line = (TYPE *)(canvasBuffer + bpl*y);
  193.     point = &line[start];            
  194.     n = end-start;                
  195.         pixel = f->color.pixel;
  196.         alpha = f->color.alpha;
  197.         if (alpha == ALPHA_OPAQUE) {
  198.             while (n--) { 
  199.         *point = pixel;
  200.         point++;            
  201.             }
  202.         } else {
  203.             while (n--) { 
  204.         *point = mix_alpha(*point, pixel, alpha);
  205.         point++;            
  206.             }
  207.         }
  208. }
  209.  
  210. void
  211. GraphicDevice32::fillLineBitmap(FillStyleDef *f, long y, long start, long end)
  212. {
  213.     int n;
  214.     long x1,y1,dx,dy;
  215.     Matrix *m = &f->bitmap_matrix;
  216.     Bitmap *b = f->bitmap;
  217.     unsigned char *pixels;
  218.     TYPE *p;
  219.     Color *cmap;
  220.     long pixbpl;
  221.     TYPE pixel;
  222.     int offset;
  223.     unsigned char *alpha_table;
  224.  
  225.     /* safety test) */
  226.     if (!b) return;
  227.  
  228.     if (clip(y,start,end)) return;
  229.     
  230.     start /= FRAC;
  231.     end /= FRAC;
  232.     n = end - start;
  233.     p = (TYPE *) (this->canvasBuffer + this->bpl*y + start * sizeof(TYPE));
  234.     
  235.     /* the coordinates in the image are normalized to 16 bits */
  236.     x1 = (long) (m->a * start + m->b * y + m->tx);
  237.     y1 = (long) (m->c * start + m->d * y + m->ty);
  238.     dx = (long) (m->a);
  239.     dy = (long) (m->c);
  240.     
  241.     pixels = b->pixels;
  242.     pixbpl = b->bpl;
  243.     cmap = f->cmap;
  244.  
  245.     if (b->alpha_buf == NULL) {
  246.         while (n) {
  247.             if (x1 >= 0 && y1 >= 0 && 
  248.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  249.                 
  250.                 pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]].pixel;
  251.                 *p = pixel;
  252.             }
  253.             x1 += dx;
  254.             y1 += dy;
  255.             p++;
  256.             n--;
  257.         }
  258.     } else if (f->alpha_table) {
  259.         alpha_table = f->alpha_table;
  260.         while (n) {
  261.             if (x1 >= 0 && y1 >= 0 && 
  262.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  263.                 
  264.                 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
  265.                 pixel = cmap[pixels[offset]].pixel;
  266.                 *p = mix_alpha(*p, pixel, alpha_table[b->alpha_buf[offset]]);
  267.             }
  268.             x1 += dx;
  269.             y1 += dy;
  270.             p++;
  271.             n--;
  272.         }
  273.     } else {
  274.         while (n) {
  275.             if (x1 >= 0 && y1 >= 0 && 
  276.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  277.                 
  278.                 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
  279.                 pixel = cmap[pixels[offset]].pixel;
  280.                 *p = mix_alpha(*p, pixel, b->alpha_buf[offset]);
  281.             }
  282.             x1 += dx;
  283.             y1 += dy;
  284.             p++;
  285.             n--;
  286.         }
  287.     }
  288. }
  289.  
  290. void
  291. GraphicDevice32::fillLineLG(Gradient *grad, long y, long start, long end)
  292. {
  293.     long dr,r,v,r2;
  294.     register long n;
  295.     TYPE *line;
  296.     TYPE *point;
  297.         Color *cp,*ramp;
  298.         Matrix *m = &grad->imat;
  299.         unsigned int start_alpha,end_alpha;
  300.  
  301.     if (clip(y,start,end)) return;
  302.  
  303.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  304.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  305.         
  306.     start /= FRAC;
  307.     end /= FRAC;
  308.  
  309.     n = end-start;
  310.  
  311.         r = (long) (m->a * start + m->b * y + m->tx);
  312.         dr = (long) (m->a);
  313.  
  314.         ramp = grad->ramp;
  315.  
  316.         line = (TYPE *)(canvasBuffer + bpl*y);
  317.     point = &line[start];    
  318.  
  319.         r2 = r + n * dr;
  320.         if ( ((r | r2) & ~255) == 0 ) {
  321.             if (!grad->has_alpha) {
  322. #ifdef FULL_AA
  323.         if (start_alpha < 255) {
  324.                     v = r>>16;
  325.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
  326.                     point++;
  327.                     r += dr;
  328.             n--;
  329.         }
  330. #endif /* FULL_AA */
  331.                 while (n>0) {
  332.                     v = r>>16;
  333.                     *point = (TYPE)ramp[v].pixel;    
  334.                     point++;                
  335.                     r += dr;                
  336.             n--;
  337.                 }
  338. #ifdef FULL_AA
  339.         if (end_alpha > 0) {
  340.                     v = r>>16;
  341.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
  342.         }
  343. #endif /* FULL_AA */
  344.             } else {
  345.                 while (n--) {
  346.                     v = r>>16;
  347.                     cp = &ramp[v];
  348.                     *point = mix_alpha(*point, cp->pixel, cp->alpha);
  349.                     point++;
  350.                     r += dr;
  351.                 }
  352.             }
  353.         } else {
  354.             if (!grad->has_alpha) {
  355. #ifdef FULL_AA
  356.         if (start_alpha < 255) {
  357.                     v = r>>16;
  358.                     if (v < 0) v = 0;
  359.                     else if (v > 255) v = 255;
  360.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
  361.                     point++;
  362.                     r += dr;
  363.             n--;
  364.         }
  365. #endif /* FULL_AA */
  366.                 while (n>0) {
  367.                     v = r>>16;
  368.                     if (v < 0) v = 0;
  369.                     else if (v > 255) v = 255;
  370.                     *point = (TYPE)ramp[v].pixel;    
  371.                     point++;                
  372.                     r += dr;                
  373.             n--;
  374.                 }
  375. #ifdef FULL_AA
  376.         if (end_alpha > 0) {
  377.                     v = r>>16;
  378.                     if (v < 0) v = 0;
  379.                     else if (v > 255) v = 255;
  380.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
  381.         }
  382. #endif /* FULL_AA */
  383.             } else {
  384.                 while (n--) {
  385.                     v = r>>16;
  386.                     if (v < 0) v = 0;
  387.                     else if (v > 255) v = 255;
  388.                     cp = &ramp[v];
  389.                     *point = mix_alpha(*point, cp->pixel, cp->alpha);
  390.                     point++;
  391.                     r += dr;
  392.                 }
  393.             }
  394.         }
  395. }
  396.  
  397. void
  398. GraphicDevice32::fillLineRG(Gradient *grad, long y, long start, long end)
  399. {
  400.     long X,dx,r,Y,dy;
  401.     long dist2;
  402.     register long   n;
  403.         Color *cp,*ramp;
  404.     TYPE *line;                            
  405.     TYPE *point;                            
  406.         Matrix *m = &grad->imat;
  407.         unsigned int start_alpha,end_alpha;
  408.  
  409.     if (clip(y,start,end)) return;
  410.  
  411.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  412.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  413.         
  414.     start /= FRAC;
  415.     end /= FRAC;
  416.  
  417.     n = end-start;
  418.         
  419.         X = (long) (m->a * start + m->b * y + m->tx);
  420.         Y = (long) (m->c * start + m->d * y + m->ty);
  421.         dx = (long) (m->a);
  422.         dy = (long) (m->c);
  423.  
  424.         ramp = grad->ramp;
  425.                                     
  426.     line = (TYPE *)(canvasBuffer + bpl*y);
  427.     point = &line[start];
  428.                  
  429.         if (!grad->has_alpha) {
  430. #ifdef FULL_AA
  431.         if (start == end) {
  432.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  433.             if ((unsigned long)dist2 >= 65536) {
  434.                 r = 255;                    
  435.             } else {                        
  436.                 r = SQRT[dist2];    
  437.             }
  438.             *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha + end_alpha - 255);
  439.         } else {
  440.             if (start_alpha < 255) {
  441.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  442.             if ((unsigned long)dist2 >= 65536) {
  443.                 r = 255;                    
  444.             } else {                        
  445.                 r = SQRT[dist2];    
  446.             }
  447.             *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha);
  448.             point++;
  449.             X += dx;                        
  450.             Y += dy;                        
  451.             n--;
  452.             }
  453. #endif /* FULL_AA */
  454.             while (n>0) {                    
  455.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  456.             if ((unsigned long)dist2 >= 65536) {
  457.                 r = 255;                    
  458.             } else {                        
  459.                 r= SQRT[dist2];    
  460.             }
  461.             *point = (TYPE)ramp[r].pixel;
  462.             point++;                     
  463.             X += dx;                        
  464.             Y += dy;                        
  465.             n--;
  466.             }        
  467. #ifdef FULL_AA
  468.             if (end_alpha > 0) {
  469.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  470.             if ((unsigned long)dist2 >= 65536) {
  471.                 r = 255;                    
  472.             } else {                        
  473.                 r= SQRT[dist2];    
  474.             }
  475.             *point = mix_alpha(*point, (TYPE)ramp[r].pixel, end_alpha);
  476.             }
  477.         }
  478. #endif /* FULL_AA */
  479.  
  480.         } else {
  481.             while (n--) {                    
  482.         dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  483.         if ((unsigned long)dist2 >= 65536) {
  484.                     r = 255;                    
  485.         } else {                        
  486.                     r= SQRT[dist2];    
  487.         }
  488.                 cp = &ramp[r];
  489.         *point = mix_alpha(*point, cp->pixel, cp->alpha);
  490.         point++;
  491.         X += dx;                        
  492.         Y += dy;                        
  493.             }        
  494.         }
  495. }
  496.  
  497. void
  498. GraphicDevice32::drawLine(long x1, long y1, long x2, long y2, long width)
  499. {
  500.     int n,adr,dx,dy,sx,color;
  501.     register int a;
  502.     register TYPE *pp;
  503.     int alpha;
  504.  
  505.     x1 = (x1) >> FRAC_BITS;
  506.     y1 = (y1) >> FRAC_BITS;
  507.     x2 = (x2) >> FRAC_BITS;
  508.     y2 = (y2) >> FRAC_BITS;
  509.     
  510.     if (y1 > y2 || (y1 == y2 && x1 > x2)) {
  511.         long tmp;
  512.  
  513.         tmp=x1;
  514.         x1=x2;
  515.         x2=tmp;
  516.  
  517.         tmp=y1;
  518.         y1=y2;
  519.         y2=tmp;
  520.     }
  521.  
  522.     if (y1 == y2 && (y1 < clip_rect.ymin || y1 > clip_rect.ymax)) return;
  523.     if (x1 == x2 && (x1 < clip_rect.xmin || x1 > clip_rect.xmax)) return;
  524.     if (x1 == x2 && y1 == y2) return;    // Bad !!!
  525.  
  526.     if (y1 < clip_rect.ymin && y1 != y2) {
  527.     x1 += (x2-x1)*(clip_rect.ymin-y1)/(y2-y1);
  528.     y1 = clip_rect.ymin;
  529.     }
  530.  
  531.     if (y2 > clip_rect.ymax && y1 != y2) {
  532.     x2 -= (x2-x1)*(y2-clip_rect.ymax)/(y2-y1);
  533.     y2 = clip_rect.ymax;
  534.     }
  535.  
  536.     if (x1 < x2) {
  537.         if (x1 < clip_rect.xmin && x1 != x2) {
  538.         y1 += (y2-y1)*(clip_rect.xmin-x1)/(x2-x1);
  539.         x1 = clip_rect.xmin;
  540.         }
  541.  
  542.         if (x2 > clip_rect.xmax && x1 != x2) {
  543.         y2 -= (y2-y1)*(x2-clip_rect.xmax)/(x2-x1);
  544.         x2 = clip_rect.xmax;
  545.         }
  546.     }
  547.  
  548.     if (x1 > x2) {
  549.         if (x2 < clip_rect.xmin && x2 != x1) {
  550.         y2 -= (y2-y1)*(clip_rect.xmin-x2)/(x1-x2);
  551.         x2 = clip_rect.xmin;
  552.         }
  553.  
  554.         if (x1 > clip_rect.xmax && x2 != x1) {
  555.         y1 += (y2-y1)*(x1-clip_rect.xmax)/(x1-x2);
  556.         x1 = clip_rect.xmax;
  557.         }
  558.     }
  559.  
  560.     // Check again
  561.     if (x1 == x2 && y1 == y2) return;
  562.     if (x1 < clip_rect.xmin || x2 < clip_rect.xmin) return;
  563.     if (y1 < clip_rect.ymin || y2 < clip_rect.ymin) return;
  564.     if (x1 > clip_rect.xmax || x2 > clip_rect.xmax) return;
  565.     if (y1 > clip_rect.ymax || y2 > clip_rect.ymax) return;
  566.  
  567.     sx=bpl >> 1;
  568.     adr=(y1 * sx + x1);
  569.     pp = (TYPE *)canvasBuffer + adr;
  570.     
  571.     dx = x2 - x1;
  572.     dy = y2 - y1;
  573.  
  574.     color = allocColor(foregroundColor);
  575.     alpha = foregroundColor.alpha;
  576.  
  577.     if (alpha == ALPHA_OPAQUE) {
  578.  
  579. #define PUTPIXEL()                 \
  580.   {                        \
  581.       *pp=color;                        \
  582.   }
  583.  
  584. #define DRAWLINE(dx,dy,inc_1,inc_2) \
  585.     n=dx;\
  586.     a=2*dy-dx;\
  587.     dy=2*dy;\
  588.     dx=2*dx-dy;\
  589.      do {\
  590.       PUTPIXEL();\
  591.             if (a>0) { pp+=(inc_1); a-=dx; }\
  592.             else { pp+=(inc_2); a+=dy; }\
  593.      } while (--n >= 0);
  594.  
  595. /* fin macro */
  596.  
  597.   if (dx == 0 && dy == 0) {
  598.     PUTPIXEL();
  599.   } else if (dx > 0) {
  600.     if (dx >= dy) {
  601.       DRAWLINE(dx, dy, sx + 1, 1);
  602.     } else {
  603.       DRAWLINE(dy, dx, sx + 1, sx);
  604.     }
  605.   } else {
  606.     dx = -dx;
  607.     if (dx >= dy) {
  608.       DRAWLINE(dx, dy, sx - 1, -1);
  609.     } else {
  610.       DRAWLINE(dy, dx, sx - 1, sx);
  611.     }
  612.   }
  613.  
  614.  
  615. #undef DRAWLINE
  616. #undef PUTPIXEL
  617.     } else {
  618. #define PUTPIXEL()                 \
  619.   {                        \
  620.       *pp=mix_alpha(*pp,color,alpha);            \
  621.   }
  622.  
  623. #define DRAWLINE(dx,dy,inc_1,inc_2) \
  624.     n=dx;\
  625.     a=2*dy-dx;\
  626.     dy=2*dy;\
  627.     dx=2*dx-dy;\
  628.      do {\
  629.       PUTPIXEL();\
  630.             if (a>0) { pp+=(inc_1); a-=dx; }\
  631.             else { pp+=(inc_2); a+=dy; }\
  632.      } while (--n >= 0);
  633.  
  634. /* fin macro */
  635.  
  636.   if (dx == 0 && dy == 0) {
  637.     PUTPIXEL();
  638.   } else if (dx > 0) {
  639.     if (dx >= dy) {
  640.       DRAWLINE(dx, dy, sx + 1, 1);
  641.     } else {
  642.       DRAWLINE(dy, dx, sx + 1, sx);
  643.     }
  644.   } else {
  645.     dx = -dx;
  646.     if (dx >= dy) {
  647.       DRAWLINE(dx, dy, sx - 1, -1);
  648.     } else {
  649.       DRAWLINE(dy, dx, sx - 1, sx);
  650.     }
  651.   }
  652.  
  653.  
  654. #undef DRAWLINE
  655. #undef PUTPIXEL
  656.     }
  657. }
  658.